<template>
  <mu-h-box size="1" class="steps-box">
    <mu-v-box size="1" border-right>
      <mu-bar v-if="!readonly" class="pad-tb-8 pad-lr-16" border-bottom>
        <span>计算步骤及属性：</span>
        <mu-button
          button-type="primary"
          :disabled="rebar"
          icon-class="ipm-iconplus-circle"
          @click="addStep">
          增加计算步骤
        </mu-button>
        <mu-button
          button-type="danger"
          :disabled="rebar || !checkedSteps.length"
          icon-class="ipm-icondelete"
          @click="deleteStep" />
        <span>操作符：</span>
        <mu-button-group>
          <mu-button v-for="item in operators" :key="item" :disabled="!activeStepId" @click="insertOperator(item)">
            {{ item }}
          </mu-button>
        </mu-button-group>

        <mu-button :disabled="!activeStepId" icon-class="ipm-iconselect" @click="funcDialogVisible = true">
          插入函数
        </mu-button>
        <mu-dialog
          v-model="funcDialogVisible"
          mask-action="none"
          width="800px"
          :footer="false"
          height="600px"
          title="插入函数"
        >
          <function-selector class="mu-absolute-fit" cellpadding @selected="onFunctionSelected" />
        </mu-dialog>
      </mu-bar>
      <mu-h-box v-if="stepList.length" class="step-header pad-t-16 pad-lr-16">
        <mu-v-box v-if="!readonly"
          size="60px"
          style="min-width:60px;"
          class="pad-tb-10 pad-lr-8 bg-grid"
          border-top border-left
          align-items="center"
          justify-content="center">
          <input
            v-model="checkedAll"
            class="checkbox"
            type="checkbox"
            name="checkbox"
            :disabled="rebar"
            @input="checkboxChange">
        </mu-v-box>
        <mu-v-box size="200px" class="pad-tb-10 pad-lr-8 bg-grid" border-top border-left>步骤/说明</mu-v-box>
        <mu-v-box size="auto"
          style="min-width:150px;"
          class="pad-tb-10 pad-lr-8 bg-grid" border-top border-left>
          计算公式
        </mu-v-box>
        <mu-v-box :size="`${showUnit?'200':'202'}px`" class="pad-tb-10 pad-lr-8 bg-grid"
          border-top border-left :border-right="!showUnit">
          计算结果/选择
        </mu-v-box>
        <mu-v-box v-if="showUnit" size="82px"
          class="pad-tb-10 pad-lr-8 bg-grid"
          border-top border-left border-right text-align="center">
          单位
        </mu-v-box>
      </mu-h-box>
      <mu-v-box v-if="stepList.length" size="1" class="step-body pad-b-16 pad-lr-16">
        <step-item
          v-for="(step, index) in stepList"
          :key="step.id || index"
          :ref="getRefName(step.id || index)"
          :class="`step-item ${selectedStepId===step.id?'active':''}`"
          :step="step"
          :checked="step.checked"
          :readonly="readonly"
          :rebar="rebar"
          :is-active="activeStepId===step.id"
          :all-names="stepNames"
          :show-unit="showUnit"
          @active="setActiveStepId"
          @selected="setSelectedStepId"
          @update="updateStep"
          @checked="checkStep"
        />
      </mu-v-box>

      <mu-v-box v-else class="h-100">
        <empty-panel tip-text="当前暂无计算步骤">
          <div v-if="!readonly">
            建议您：<mu-button button-type="primary" :disabled="rebar" icon-class="ipm-iconplus-circle" @click="addStep">
              增加计算步骤
            </mu-button>
          </div>
        </empty-panel>
      </mu-v-box>
    </mu-v-box>
    <mu-v-box size="30%">
      <mu-bar v-if="!readonly" class="pad-tb-8 pad-lr-16" border-bottom>
        <mu-button icon-class="ipm-iconselect" @click="addParams"> 插入字段 </mu-button>
        <mu-button
          button-type="danger"
          :disabled="!activeParams"
          icon-class="ipm-icondelete"
          @click="deleteParams" />
      </mu-bar>
      <kaka-grid
        v-if="paramList.length"
        ref="paramsGrid"
        class="h-100 pad-lr-16 pad-t-16"
        key-field="id"
        parent-key-field="parentId"
        :columns="paramsGridColumns"
        :records="paramList"
        @load="paramsOnLoad"
        @cellselect="paramsGridSelect"
        @cellchange="paramsGridChange"
      />
      <mu-v-box v-else class="h-100">
        <empty-panel tip-text="当前暂无计算属性">
          <div v-if="!readonly">
            建议您：<mu-button icon-class="ipm-iconselect" @click="addParams"> 插入字段 </mu-button>
          </div>
        </empty-panel>
      </mu-v-box>
    </mu-v-box>
  </mu-h-box>
</template>

<script>
  import StepItem from './step-item.vue'
  import cloneDeep from 'lodash.clonedeep'
  import FunctionSelector from './function-selector.vue'

  export default {
    components: {
      StepItem,
      FunctionSelector
    },
    props: {
      steps: {
        type: Array,
        required: true
      },
      params: {
        type: Array,
        required: true
      },
      readonly: {
        type: Boolean,
        default: false
      },
      rebar: {
        type: Boolean,
        default: false
      },
      showUnit: {
        type: Boolean,
        default: true
      }
    },
    data () {
      return {
        operators: ['+', '-', '*', '/', '^', '()', 'PI'],
        activeStepId: null,
        selectedStepId: null,
        funcDialogVisible: false,
        checkedSteps: [],
        activeParams: null,
        checkedAll: false
      }
    },

    computed: {
      stepList () {
        return cloneDeep(this.steps)
      },

      paramList () {
        return cloneDeep(this.params)
      },

      stepNames () {
        return this.steps.map(item => item.name)
      },
      activeStep () {
        return this.getRawStepById(this.activeStepId)
      },
      someActiveStepId () {
        return this.activeStepId &&
          this.stepList.some(v => v.id === this.activeStepId)
      },

      paramsGridColumns () {
        return [
          {
            field: 'name',
            tooltip: 'name',
            caption: '属性名称',
            width: 'auto',
            minWidth: 100,
            headerStyle: {
              textAlign: 'center'
            },
            style: (rec) => {
              return {
                ...this.setParamsGridStyle(rec),
                padding: [0, 0, 0, 0]
              }
            },
            columnType: new kakaGrid.columns.type.TreeColumn({
              draw: (value, ctx, opt, info) => {
                if (this.readonly) return
                var index = opt.grid.dataSource.getIndexByKey(opt.record.id)
                var treeInfo = opt.grid.dataSource.getTreeInfo(index)
                ctx.save()
                try {
                  const x = opt.rect.left + opt.rect.width - 30
                  const y = opt.rect.top + (opt.rect.height - 12) / 2
                  let valueLeft = opt.rect.left + 40
                  let valueRight = 12
                  if (opt.record.parentId !== -1) {
                    const InsertWidth = ctx.measureText('插入').width + 16
                    valueRight += InsertWidth
                    ctx.fillStyle = '#008cd6'
                    ctx.fillText('插入', x, y)
                    valueLeft += 20
                  } else {
                    // 画线
                    ctx.strokeStyle = '#333'
                    ctx.beginPath()
                    ctx.strokeRect(opt.rect.left + 12, opt.rect.top + 12, 16, 16)
                    ctx.closePath()
                    ctx.beginPath()
                    ctx.moveTo(opt.rect.left + 16, opt.rect.top + 20)
                    ctx.lineTo(opt.rect.left + 24, opt.rect.top + 20)
                    if (!treeInfo.expanded) {
                      ctx.moveTo(opt.rect.left + 20, opt.rect.top + 16)
                      ctx.lineTo(opt.rect.left + 20, opt.rect.top + 24)
                    }
                    ctx.stroke()
                  }
                  const valueWidth = ctx.measureText(value).width
                  if (valueWidth > opt.rect.width - valueRight - 40) {
                    const sW = ctx.measureText('...').width
                    const sreLN = valueWidth / (opt.rect.width - 40 - valueRight - sW)
                    const strlen = parseInt(value.length / sreLN)
                    value = value.substr(0, strlen) + '...'
                  }
                  ctx.fillStyle = '#333'
                  ctx.fillText(value, valueLeft, y)
                } finally {
                  ctx.restore()
                }
                return false
              }
            }),

            action: new kakaGrid.columns.action.InlineInputEditor({
              type: 'text',
              disableInput: true,
              disableAction: (rec) => rec.parentId === -1 || this.readonly,
              action: (rec) => {
                if (rec.name) {
                  this.insertOperator(rec.name)
                }
              }
            })
          },
          {
            field: rec => rec.unit || '- -',
            caption: '单位',
            align: 'center',
            width: 60,
            minWidth: 60,
            style: (rec) => this.setParamsGridStyle(rec)
          },
          {
            field: 'propertyValue',
            caption: '属性值',
            headerStyle: {
              textAlign: 'center'
            },
            width: 140,
            minWidth: 60,
            style: (rec) => this.setParamsGridStyle(rec),
            readonly: (rec) => rec.parentId === -1 || this.readonly
          }
        ]
      }
    },

    watch: {
      someActiveStepId (val) {
        if (!val) {
          this.activeStepId = null
        }
      }
    },

    methods: {

      initSteps () {
        this.checkedAll = false
        this.activeStepId = null
        this.selectedStepId = null
        this.checkedSteps = []
      },

      initParams () {
        this.activeParams = null
      },

      // 属性表格加载
      paramsOnLoad (vm) {
        vm.kakaGrid.singleSelection = true // 单选
        vm.kakaGrid.dataSource.expandAll() // 展开
        vm.invalidate()
      },

      // 属性表格选中行
      paramsGridSelect ({ row, col }, selected, vm) {
        const record = vm.kakaGrid.getRowRecord(row)
        if (selected) {
          this.activeParams = record || null
          vm.invalidate()
        }
      },

      // 属性表格修改
      paramsGridChange (data) {
        this.$emit('updateParams', data.record)
      },

      // 设置属性表格背景颜色
      setParamsGridStyle (rec) {
        if (this.activeParams && rec.id === this.activeParams.id) {
          return { bgColor: '#f4fbff' }
        }
      },

      addStep () {
        const nameMaxNo = this.steps.reduce((maxNo, step) => {
          const nameNo = Number(step.name.replace('#L', ''))
          if (nameNo > maxNo) {
            maxNo = nameNo
          }
          return maxNo
        }, 0)
        this.$emit('add', { name: `#L${nameMaxNo + 1}` })
      },

      addParams () {
        this.$emit('addParams')
      },

      deleteParams () {
        this.$emit('deleteParams', this.activeParams)
      },

      setActiveStepId (id) {
        this.activeStepId = id
      },

      setSelectedStepId (id) {
        this.selectedStepId = id
      },

      updateStep (step) {
        this.$emit('update', step)
      },

      deleteStep () {
        this.$emit('delete', this.checkedSteps)
      },

      checkStep (data) {
        const stepIndex = this.stepList.findIndex(z => z.id === data.id)
        this.stepList[stepIndex].checked = data.checked
        if (data.checked) {
          this.checkedSteps.push(data.id)
          if (this.checkedSteps.length === this.steps.length) {
            this.checkedAll = true
          }
          return
        }
        const index = this.checkedSteps.findIndex(id => id === data.id)
        if (index !== -1) {
          this.checkedSteps.splice(index, 1)
          if (this.checkedAll) {
            this.checkedAll = false
          }
        }
      },

      onFunctionSelected (formula) {
        this.insertOperator(formula)
        this.funcDialogVisible = false
      },

      insertOperator (operator) {
        if (!this.activeStepId) {
          return
        }
        const refName = this.getRefName(this.activeStepId)
        this.$refs[refName][0].insert(operator)
      },

      getRefName (id) {
        return 'step' + id
      },

      getRawStepById (id) {
        return this.steps.find((item) => item.id === id)
      },

      checkboxChange (event) {
        const { checked } = event.target
        this.stepList.forEach(ele => {
          ele.checked = checked
        })
        this.checkedSteps = this.stepList.filter(z => z.checked).map(item => item.id)
        this.$emit('checkAll', checked)
      }
    }
  }
</script>

<style scoped>

.steps-box {
  overflow: auto;
  position: relative;
  height: 100%;
}

.mu-bar {
  min-width: 650px;
}

.step-header {
  overflow: hidden;
  min-width: 650px;
}

.step-body {
  overflow: hidden overlay;
  min-width: 650px;
}

.step-body .step-item {
  border: 1px solid #ebecf0 !important;
  height: 81px;
  min-height: 81px;
  max-height: 81px;
}

.step-body .step-item.active {
  background-color: #f4fbff !important;
}

.step-body :not(:last-child).step-item {
  border-bottom: none !important;
}

  input[type=checkbox]:not([disabled]) {
    cursor: pointer;
    position: relative;
  }

  input[type=checkbox]::after {
    position: absolute;
    top: 0;
    background-color: #fff;
    color: #fff;
    width: 14px;
    height: 14px;
    display: inline-block;
    visibility: visible;
    padding-left: 0px;
    text-align: center;
    content: ' ';
    border-radius: 2px;
    box-sizing: border-box;
    border: 1px solid #ddd;
  }

  input[type=checkbox][disabled]::after {
    background-color: #eeeeee;
  }

  input[type=checkbox]:checked::after {
    content: "";
    background-color: #037DF3;
    border-color: #037DF3;
    background-color: #037DF3;
  }

  input[type=checkbox]:checked::before {
    content: '';
    position: absolute;
    top: 1px;
    left: 5px;
    width: 3px;
    height: 8px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    z-index: 1;
  }
</style>
